home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / GNUPLOTsrc.lha / command.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-22  |  39.8 KB  |  1,595 lines

  1. #ifndef lint
  2. static char    *RCSid = "$Id: command.c,v 1.92 1995/12/14 21:08:54 drd Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - command.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  * 
  10.  * Permission to use, copy, and distribute this software and its documentation
  11.  * for any purpose with or without fee is hereby granted, provided that the
  12.  * above copyright notice appear in all copies and that both that copyright
  13.  * notice and this permission notice appear in supporting documentation.
  14.  * 
  15.  * Permission to modify the software is granted, but not the right to distribute
  16.  * the modified code.  Modifications are to be distributed as patches to
  17.  * released version.
  18.  * 
  19.  * This software is provided "as is" without express or implied warranty.
  20.  * 
  21.  * 
  22.  * AUTHORS
  23.  * 
  24.  * Original Software: Thomas Williams,  Colin Kelley.
  25.  * 
  26.  * Gnuplot 2.0 additions: Russell Lang, Dave Kotz, John Campbell.
  27.  * 
  28.  * Gnuplot 3.0 additions: Gershon Elber and many others.
  29.  * 
  30.  *   Nonlinear Least squares fit:
  31.  *     Carsten Grammes
  32.  * 
  33.  * Changes:
  34.  * 
  35.  * Feb 5, 1992    Jack Veenstra    (veenstra@cs.rochester.edu) Added support to
  36.  * filter data values read from a file through a user-defined function before
  37.  * plotting. The keyword "thru" was added to the "plot" command. Example
  38.  * syntax: f(x) = x / 100 plot "test.data" thru f(x) This example divides all
  39.  * the y values by 100 before plotting. The filter function processes the
  40.  * data before any log-scaling occurs. This capability should be generalized
  41.  * to filter x values as well and a similar feature should be added to the
  42.  * "splot" command.
  43.  * 
  44.  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
  45.  * Added user-specified bases for log scaling.
  46.  * 
  47.  * There is a mailing list for gnuplot users. Note, however, that the
  48.  * newsgroup 
  49.  *    comp.graphics.gnuplot 
  50.  * is identical to the mailing list (they
  51.  * both carry the same set of messages). We prefer that you read the
  52.  * messages through that newsgroup, to subscribing to the mailing list.
  53.  * (If you can read that newsgroup, and are already on the mailing list,
  54.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  55.  * removed from the mailing list.)
  56.  *
  57.  * The address for mailing to list members is
  58.  *       info-gnuplot@dartmouth.edu
  59.  * and for mailing administrative requests is 
  60.  *       info-gnuplot-request@dartmouth.edu
  61.  * The mailing list for bug reports is 
  62.  *       bug-gnuplot@dartmouth.edu
  63.  * Send bug reports regarding the fit to
  64.  *       cagr@rz.uni-sb.de
  65.  * The list of those interested in beta-test versions is
  66.  *       info-gnuplot-beta@dartmouth.edu
  67.  */
  68.  
  69. #include <math.h>
  70. #include <ctype.h>
  71. #include <assert.h>
  72.  
  73. #ifdef AMIGA_AC_5
  74. void            sleep();    /* defined later */
  75. #endif
  76.  
  77. #ifdef VMS
  78. #include <signal.h>  /* for sleep() */
  79. #endif
  80.  
  81. #if defined(MSDOS) || defined(DOS386)
  82. #ifdef DJGPP
  83. #include <dos.h>
  84. #else
  85. #include <process.h>
  86. #endif
  87.  
  88. #ifdef __ZTC__
  89. #define P_WAIT 0
  90. #else
  91.  
  92. #ifdef __TURBOC__
  93. #ifndef _Windows
  94. #include <dos.h>        /* sleep() */
  95. #include <conio.h>
  96. #include <dir.h>    /* setdisk() */
  97. extern unsigned _stklen = 16394;/* increase stack size */
  98. extern char HelpFile[80] ;      /* patch for do_help  - DJL */
  99. #endif
  100.  
  101. #else                /* must be MSC */
  102. #if !defined(__EMX__) && !defined(DJGPP)
  103. #ifdef __MSC__
  104. #include <direct.h>        /* for _chdrive() */
  105. #endif
  106. void            sleep();    /* defined later */
  107. #endif                /* !__EMX__ && !DJGPP */
  108. #endif                /* TURBOC */
  109. #endif                /* ZTC */
  110.  
  111. #endif                /* MSDOS */
  112.  
  113. #ifdef AMIGA_SC_6_1
  114. #include <proto/dos.h>
  115. void            sleep();
  116. #endif                /* AMIGA_SC_6_1 */
  117.  
  118. #include "plot.h"
  119. #include "setshow.h"
  120. #include "fit.h"
  121. #include "binary.h"
  122. #ifndef _Windows
  123. #include "help.h"
  124. #else
  125. #define MAXSTR 255
  126. #endif
  127.  
  128. #if defined(ATARI) || defined(MTOS)
  129. #ifdef __PUREC__
  130. #include <ext.h>
  131. #include <tos.h>
  132. #include <aes.h>
  133. #include <float.h>        /* get FLT_MAX */
  134. #else
  135. #include <osbind.h>
  136. #include <aesbind.h>
  137. #include <support.h>
  138. #endif /* __PUREC__ */
  139. #endif /* ATARI || MTOS */
  140.  
  141. #ifndef STDOUT
  142. #define STDOUT 1
  143. #endif
  144.  
  145. #ifndef HELPFILE
  146. #if defined( MSDOS ) || defined( OS2 ) || defined(DOS386)
  147. #define HELPFILE "gnuplot.gih"
  148. #else
  149. #ifdef AMIGA_SC_6_1
  150. #define HELPFILE "S:gnuplot.gih"
  151. #else
  152. #define HELPFILE "docs/gnuplot.gih"    /* changed by makefile */
  153. #endif                /* AMIGA_SC_6_1 */
  154. #endif
  155. #endif                /* HELPFILE */
  156.  
  157. #ifdef _Windows
  158. #include <windows.h>
  159. #ifdef __MSC__
  160. #include <malloc.h>
  161. #else
  162. #include <alloc.h>
  163. #include <dir.h>    /* setdisk() */
  164. #endif
  165. #include "win/wgnuplib.h"
  166. void sleep();
  167. extern TW textwin;
  168. extern LPSTR winhelpname;
  169. extern void screen_dump(void);    /* in term/win.trm */
  170. extern int Pause(LPSTR mess); /* in winmain.c */
  171. #endif
  172.  
  173. #define inrange(z,min,max) ((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
  174.  
  175. /* purec_sscanf is now in datafile.c */
  176. #ifdef __PUREC__
  177. # define sscanf purec_sscanf
  178. #endif
  179.  
  180. #ifdef OS2
  181.  /* emx has getcwd, chdir that can handle drive names */
  182. #define getcwd _getcwd2
  183. #define chdir  _chdir2
  184. #endif /* OS2 */
  185.  
  186. #if (defined(unix) || defined(OSK))
  187. #ifdef GETCWD
  188. extern char    *getcwd();    /* some Unix's use getcwd */
  189. #else
  190. extern char    *getwd();    /* most Unix's use getwd */
  191. #endif
  192. #else
  193. #ifdef DJGPP
  194. extern char    *getwd();    /* DJGPP acts like Unix here */
  195. #else
  196. extern char    *getcwd();    /* Turbo C, MSC, EMX, OS2 and VMS use getcwd */
  197. #endif
  198. #endif
  199.  
  200. #ifdef vms
  201. int             vms_vkid;    /* Virtual keyboard id */
  202. #endif
  203.  
  204.  
  205. /* static prototypes */
  206.  
  207. static void replotrequest __P((void));
  208. static int command __P((void));
  209. static int read_line __P((char *prompt));
  210. static void do_shell __P((void));
  211. static void do_help __P((void));
  212. static void do_system __P((void));
  213. static int changedir __P((char *path));
  214. static void getpath __P((char *string));
  215.  
  216. #if defined(AMIGA_SC_6_1)
  217. void sleep __P((unsigned int delay));
  218. #endif
  219.  
  220. extern int      chdir();
  221.  
  222. /* input data, parsing variables */
  223. #ifdef AMIGA_SC_6_1
  224.  __far int             num_tokens, c_token;
  225. #else
  226.  int             num_tokens, c_token;
  227. #endif
  228.  
  229. extern TBOOLEAN  do_load_arg_substitution;
  230. struct lexical_unit *token=NULL;
  231. int token_table_size=0;
  232.  
  233. char *input_line=NULL;
  234. int input_line_len=0;
  235. int inline_num = 0;    /* input line number */
  236.  
  237. /* things shared by plot2d.c and plot3d.c are here, for historical reasons */
  238.  
  239. double          min_array[AXIS_ARRAY_SIZE], max_array[AXIS_ARRAY_SIZE];
  240. int             auto_array[AXIS_ARRAY_SIZE];
  241. TBOOLEAN        log_array[AXIS_ARRAY_SIZE];
  242. double          base_array[AXIS_ARRAY_SIZE];
  243. double          log_base_array[AXIS_ARRAY_SIZE];
  244. struct udft_entry *dummy_func=NULL;  /* NULL means no dummy vars active */
  245.  
  246. char            c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN + 1];    /* current dummy vars */
  247.  
  248.  
  249. /* support for replot command */
  250. char *replot_line=NULL;
  251. int      plot_token;    /* start of 'plot' command */
  252.  
  253. /* If last plot was a 3d one. */
  254. TBOOLEAN         is_3d_plot = FALSE;
  255.  
  256.  
  257. extern TBOOLEAN term_graphics, term_suspended;
  258.  
  259. #ifndef min
  260. #define min(a,b)    ((a)>(b) ? (b) : (a))
  261. #endif
  262. #define Inc_c_token if (++c_token >= num_tokens)    \
  263.                         int_error ("Syntax error", c_token);
  264.  
  265.  
  266. /* support for dynamic size of input line */
  267.  
  268. void extend_input_line()
  269. {
  270.   if(input_line_len==0) {
  271.     /* first time */
  272.     input_line=alloc(MAX_LINE_LEN, "input_line");
  273.     input_line_len=MAX_LINE_LEN;
  274.     input_line[0]='\0';
  275.   } else {
  276.     input_line=ralloc(input_line, input_line_len+MAX_LINE_LEN, "extend input line");
  277.     input_line_len+=MAX_LINE_LEN;
  278. #ifdef DEBUG_STR
  279.     fprintf(stderr, "extending input line to %d chars\n", input_line_len);
  280. #endif
  281.   }
  282. }
  283.  
  284. void extend_token_table()
  285. {
  286.   if(token_table_size==0) {
  287.     /* first time */
  288.     token=(struct lexical_unit *)alloc(MAX_TOKENS*sizeof(struct lexical_unit), "token table");
  289.     token_table_size=MAX_TOKENS;
  290.   } else {
  291.     token=ralloc(token, (token_table_size+MAX_TOKENS)*sizeof(struct lexical_unit), "extend token table");
  292.     token_table_size+=MAX_TOKENS;
  293. #ifdef DEBUG_STR
  294.     fprintf(stderr, "extending token table to %d elements\n", token_table_size);
  295. #endif
  296.   }
  297. }
  298.  
  299. void init_memory()
  300. {
  301.   extend_input_line();
  302.   extend_token_table();
  303.   replot_line=alloc(1, "string");
  304.   *replot_line='\0';
  305. }
  306.  
  307. int com_line()
  308. {
  309.   if (multiplot) {
  310.       if (term_graphics && !term_suspended && interactive) {
  311.       /* make sure that it is safe to issue an interactive prompt */
  312.       if ( (term->flags & TERM_CAN_MULTIPLOT) ||
  313.                 ( (outfile!=stdout) && !(term->flags & TERM_CANNOT_MULTIPLOT) )
  314.            )
  315.    {
  316.        /* it's okay to use multiplot here */
  317.        if (term->suspend)
  318.            (*term->suspend)();
  319.        term_suspended = TRUE;
  320.    }
  321.    else
  322.        /* we cant do interactive multiplot here */
  323.        graph_error("Cant do interactive multiplot with this driver");
  324.     } /* interactive */
  325.     
  326.    if (read_line("multiplot> "))
  327.        return(1);
  328.  } else {
  329.    if (read_line(PROMPT))
  330.        return(1);
  331.  }
  332.  
  333.     /* So we can flag any new output: if false at time of error, */
  334.     /* we reprint the command line before printing caret. */
  335.     /* TRUE for interactive terminals, since the command line is typed. */
  336.     /* FALSE for non-terminal stdin, so command line is printed anyway. */
  337.     /* (DFK 11/89) */
  338.     screen_ok = interactive;
  339.  
  340.     if (do_line())
  341.         return(1);
  342.      else
  343.         return(0);
  344. }
  345.  
  346. #ifdef OS2
  347. int set_input_line( char *line, int nchar )
  348. {
  349.     strncpy( input_line, line, nchar ) ;
  350.     input_line[nchar]='\0';
  351. }
  352. #endif
  353.  
  354. int do_line()
  355. {                /* also used in load_file */
  356.     if (is_system(input_line[0])) {
  357.     do_system();
  358.     (void) fputs("!\n", stderr);
  359.     return(0);
  360.     }
  361.     num_tokens = scanner(input_line);
  362.     c_token = 0;
  363.     while (c_token < num_tokens) {
  364.     if (command())
  365.            return(1);
  366.     if (c_token < num_tokens)    /* something after command */
  367.         if (equals(c_token, ";"))
  368.         c_token++;
  369.         else
  370.         int_error("';' expected", c_token);
  371.     }
  372.     return(0);
  373. }
  374.  
  375.  
  376. void define()
  377. {
  378.     register int    start_token;/* the 1st token in the function definition */
  379.     register struct udvt_entry *udv;
  380.     register struct udft_entry *udf;
  381.  
  382.     if (equals(c_token + 1, "(")) {
  383.     /* function ! */
  384.     int             dummy_num = 0;
  385.     char save_dummy[MAX_NUM_VAR][MAX_ID_LEN+1];
  386.     memcpy(save_dummy, c_dummy_var, sizeof(save_dummy));
  387.     start_token = c_token;
  388.     do {
  389.         c_token += 2;    /* skip to the next dummy */
  390.         copy_str(c_dummy_var[dummy_num++], c_token, MAX_ID_LEN);
  391.     } while (equals(c_token + 1, ",") && (dummy_num < MAX_NUM_VAR));
  392.     if (equals(c_token + 1, ","))
  393.         int_error("function contains too many parameters", c_token + 2);
  394.     c_token += 3;        /* skip (, dummy, ) and = */
  395.     if (END_OF_COMMAND)
  396.         int_error("function definition expected", c_token);
  397.     udf = dummy_func = add_udf(start_token);
  398.     if (udf->at)        /* already a dynamic a.t. there */
  399.         free((char *) udf->at);    /* so free it first */
  400.     if ((udf->at = perm_at()) == (struct at_type *) NULL)
  401.         int_error("not enough memory for function", start_token);
  402.     memcpy(c_dummy_var, save_dummy, sizeof(save_dummy));
  403.     m_capture(&(udf->definition), start_token, c_token - 1);
  404.     dummy_func=NULL; /* dont let anyone else use our workspace */
  405.     } else {
  406.     /* variable ! */
  407.     start_token = c_token;
  408.     c_token += 2;
  409.     udv = add_udv(start_token);
  410.     (void) const_express(&(udv->udv_value));
  411.     udv->udv_undef = FALSE;
  412.     }
  413. }
  414.  
  415.  
  416. static int command()
  417. {
  418.     FILE *fp, *lf_top();
  419.     int             i;
  420.     char            sv_file[MAX_LINE_LEN + 1];
  421.     /* string holding name of save or load file */
  422.  
  423.     for (i = 0; i < MAX_NUM_VAR; i++)
  424.     c_dummy_var[i][0] = '\0';    /* no dummy variables */
  425.  
  426.     if (is_definition(c_token))
  427.     define();
  428.     else if (almost_equals(c_token, "h$elp") || equals(c_token, "?")) {
  429.     c_token++;
  430.     do_help();
  431.     } else if (almost_equals(c_token, "test")) {
  432.     c_token++;
  433.     test_term();
  434.     } else if (almost_equals(c_token, "scr$eendump")) {
  435.     c_token++;
  436. #ifdef _Windows
  437.     screen_dump();
  438. #else
  439.     fputs("screendump not implemented\n",stderr);
  440. #endif
  441.     } else if (almost_equals(c_token, "pa$use")) {
  442.     struct value    a;
  443.     int             stime, text = 0;
  444.     char            buf[MAX_LINE_LEN + 1];
  445.  
  446.     c_token++;
  447.     stime = (int) real(const_express(&a));
  448.     buf[0]='\0';
  449.     if (!(END_OF_COMMAND)) {
  450.         if (!isstring(c_token))
  451.         int_error("expecting string", c_token);
  452.         else {
  453.         quote_str(buf, c_token, MAX_LINE_LEN);
  454. #ifdef _Windows
  455.         if (stime>=0)
  456. #endif
  457. #ifdef OS2
  458.                 if( strcmp(term->name, "pm" )!=0 || stime >=0 )
  459. #endif
  460. #ifdef MTOS
  461.         if( strcmp(term->name, "mtos" )!=0 || stime >=0 )
  462. #endif
  463.         (void) fprintf(stderr, "%s", buf);
  464.         text = 1;
  465.         }
  466.     }
  467.     if (stime < 0)
  468. #ifdef _Windows
  469.         {
  470.             if (!Pause(buf))
  471.                  longjmp(env, TRUE); /* bail out to command line */
  472.          }
  473. #else
  474. #ifdef OS2
  475.         if( strcmp(term->name, "pm" )==0 && stime < 0 )
  476.         {
  477.             int rc ;
  478.             if( (rc=PM_pause( buf ))==0 ) longjmp(env,TRUE) ;
  479.             else if( rc==2 ) { 
  480.         (void) fprintf(stderr, "%s", buf);
  481.         text = 1;
  482.                 (void) fgets(buf, MAX_LINE_LEN, stdin);
  483.                 }    
  484.  
  485.     }
  486. #else
  487. #ifdef MTOS
  488.     {
  489.     if( strcmp(term->name, "mtos" )==0) {
  490.             int MTOS_pause(char *buf);
  491.             int rc;
  492.         if ((rc = MTOS_pause(buf)) == 0) 
  493.             longjmp(env,TRUE);
  494.             else if (rc == 2) {
  495.             (void) fprintf(stderr, "%s", buf);
  496.             text = 1;
  497.             (void) fgets(buf, MAX_LINE_LEN, stdin);
  498.         } 
  499.     }
  500.     else if( strcmp(term->name, "atari" )==0) {
  501.         char *readline(char *);
  502.         char *line=readline("");
  503.         if(line) free(line);        
  504.         }
  505.     else
  506.         (void) fgets(buf, MAX_LINE_LEN, stdin);
  507.     }
  508. #else
  509. #ifdef ATARI
  510.     {
  511.     else if( strcmp(term->name, "atari" )==0) {
  512.         char *readline(char *);
  513.         char *line=readline("");
  514.         if(line) free(line);        
  515.         }
  516.     else
  517.         (void) fgets(buf, MAX_LINE_LEN, stdin);               
  518.     }
  519. #else /* ATARI */
  520.         (void) fgets(buf, MAX_LINE_LEN, stdin);
  521.     /* Hold until CR hit. */
  522. #endif /* MTOS */
  523. #endif /* ATARI */
  524. #endif /*OS2*/
  525. #endif
  526. #ifdef __ZTC__
  527.     if (stime > 0)
  528.         usleep((unsigned long) stime);
  529. #else
  530.     if (stime > 0)
  531.         sleep((unsigned int) stime);
  532. #endif
  533.     if (text != 0 && stime >= 0)
  534.         (void) fprintf(stderr, "\n");
  535.     c_token++;
  536.     screen_ok = FALSE;
  537.     }
  538.     else if (almost_equals(c_token, "pr$int")) {
  539.     struct value    a;
  540.  
  541.     c_token++;
  542.     (void) const_express(&a);
  543.     (void) putc('\t', stderr);
  544.     disp_value(stderr, &a);
  545.     (void) putc('\n', stderr);
  546.     screen_ok = FALSE;
  547.     } else if (almost_equals(c_token,"fit")) {
  548.     ++c_token;
  549.     do_fit();
  550.     }
  551.     else if (almost_equals(c_token,"up$date")) {
  552.         char tmps[80];
  553.                 if ( !isstring(++c_token) )
  554.             int_error ("Parameter filename expected", c_token);
  555.         quote_str (tmps, c_token++, 80);
  556.         update (tmps);
  557.         }
  558.     else if (almost_equals(c_token, "p$lot")) {
  559.     plot_token = c_token++;
  560. #ifdef _Windows
  561.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  562. #endif
  563.     plotrequest();
  564. #ifdef _Windows
  565.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_ARROW));
  566. #endif
  567.     } else if (almost_equals(c_token, "sp$lot")) {
  568.     plot_token = c_token++;
  569. #ifdef _Windows
  570.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  571. #endif
  572.     plot3drequest();
  573. #ifdef _Windows
  574.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_ARROW));
  575. #endif
  576.     } else if (almost_equals(c_token, "rep$lot")) {
  577.     if (replot_line[0] == '\0')
  578.         int_error("no previous plot", c_token);
  579.     c_token++;
  580. #ifdef _Windows
  581.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  582. #endif
  583.     replotrequest();
  584. #ifdef _Windows
  585.     SetCursor(LoadCursor((HINSTANCE)NULL, IDC_ARROW));
  586. #endif
  587.     } else if (almost_equals(c_token, "se$t"))
  588.     set_command();
  589.     else if (almost_equals(c_token, "res$et"))
  590.         reset_command();
  591.     else if (almost_equals(c_token, "sh$ow"))
  592.     show_command();
  593.     else if (almost_equals(c_token, "cl$ear")) {
  594.     if (!term_init) {
  595.         (*term->init) ();
  596.         term_init = TRUE;
  597.     }
  598.     if (term_graphics) {
  599.         if (multiplot && term_suspended && term->resume)
  600.         {
  601.             (*term->resume)();
  602.             term_suspended = FALSE;
  603.         }
  604.         (*term->text)();
  605.     }
  606.     (*term->graphics) ();
  607.     (*term->text) ();
  608.     (void) fflush(outfile);
  609.     screen_ok = FALSE;
  610.     c_token++;
  611.     } else if (almost_equals(c_token, "she$ll")) {
  612.     do_shell();
  613.     screen_ok = FALSE;
  614.     c_token++;
  615.     } else if (almost_equals(c_token, "sa$ve")) {
  616.     if (almost_equals(++c_token, "f$unctions")) {
  617.         if (!isstring(++c_token))
  618.         int_error("expecting filename", c_token);
  619.         else {
  620.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  621.         save_functions(fopen(sv_file, "w"));
  622.         }
  623.     } else if (almost_equals(c_token, "v$ariables")) {
  624.         if (!isstring(++c_token))
  625.         int_error("expecting filename", c_token);
  626.         else {
  627.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  628.         save_variables(fopen(sv_file, "w"));
  629.         }
  630.     } else if (almost_equals(c_token, "s$et")) {
  631.         if (!isstring(++c_token))
  632.         int_error("expecting filename", c_token);
  633.         else {
  634.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  635.         save_set(fopen(sv_file, "w"));
  636.         }
  637.     } else if (isstring(c_token)) {
  638.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  639.         save_all(fopen(sv_file, "w"));
  640.     } else {
  641.         int_error(
  642.              "filename or keyword 'functions', 'variables', or 'set' expected",
  643.              c_token);
  644.     }
  645.     c_token++;
  646.     } else if (almost_equals(c_token, "l$oad")) {
  647.     if (!isstring(++c_token))
  648.         int_error("expecting filename", c_token);
  649.     else {
  650.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  651.         load_file(fp=fopen(sv_file, "r"), sv_file, FALSE);
  652.         /* input_line[] and token[] now destroyed! */
  653.         c_token = num_tokens = 0;
  654.     }
  655.     } else if (almost_equals(c_token,"ca$ll")) {
  656.     if (!isstring(++c_token))
  657.         int_error("expecting filename",c_token);
  658.     else {
  659.         quote_str(sv_file,c_token, MAX_LINE_LEN);
  660.         load_file(fopen(sv_file,"r"), sv_file, TRUE);    /* Argument list follows filename */
  661.         /* input_line[] and token[] now destroyed! */
  662.         c_token = num_tokens = 0;
  663.     }
  664.     } else if (almost_equals(c_token,"if")) {
  665.     float exprval;
  666.     struct value    t;
  667.     if (!equals(++c_token, "("))    /* no expression */
  668.         int_error("expecting (expression)", c_token);
  669.         exprval = real(const_express(&t));
  670.     if (exprval != 0.0) {
  671.         /* fake the condition of a ';' between commands */
  672.         int eolpos = token[num_tokens-1].start_index+token[num_tokens-1].length;
  673.         --c_token;
  674.         token[c_token].length = 1;
  675.         token[c_token].start_index = eolpos+2;
  676.         input_line[eolpos+2] = ';';
  677.         input_line[eolpos+3] = '\0';
  678.     } else
  679.         c_token = num_tokens = 0;
  680.     } else if (almost_equals(c_token,"rer$ead")) {
  681.             fp = lf_top();
  682.             if (fp != (FILE *)NULL) rewind(fp);
  683.             c_token++;
  684.     } else if (almost_equals(c_token, "cd")) {
  685.     if (!isstring(++c_token))
  686.         int_error("expecting directory name", c_token);
  687.     else {
  688.         quote_str(sv_file, c_token, MAX_LINE_LEN);
  689.         if (changedir(sv_file)) {
  690.         int_error("Can't change to this directory", c_token);
  691.         }
  692.         c_token++;
  693.     }
  694.     } else if (almost_equals(c_token, "pwd")) {
  695.     getpath(sv_file);
  696.     fprintf(stderr, "%s\n", sv_file);
  697.     c_token++;
  698.     } else if (almost_equals(c_token, "ex$it") ||
  699.            almost_equals(c_token, "q$uit")) {
  700.         /* graphics will be tidied up in main */
  701.     return(1);
  702.     } else if (!equals(c_token, ";")) {    /* null statement */
  703. #ifdef OS2
  704.         {
  705.         if( token[c_token].is_token ) { 
  706.             char cmd[80] ;
  707.            strncpy(cmd,input_line+token[c_token].start_index,token[c_token].length);
  708.             cmd[token[c_token].length] = '\0' ;               
  709.             ++c_token;
  710.             if(ExecuteMacro(cmd)==0) return(0);
  711.             }
  712.         }
  713. #endif
  714.     int_error("invalid command", c_token);
  715.     }
  716.     return(0);
  717. }
  718.  
  719.  
  720. void done(status)
  721.     int             status;
  722. {
  723.     if (term && term_init) {
  724.     (*term->reset) ();
  725.     term_init=0; /* x11 doesn't like to be reset twice */
  726.      }
  727. #ifdef vms
  728.     vms_reset();
  729. #endif
  730.     exit(status);
  731. }
  732.  
  733. static int changedir(path)
  734. char *path;
  735. {
  736. #if defined(MSDOS) || defined(_Windows) || defined(ATARI) || defined(DOS386)
  737. #if defined(__ZTC__)
  738.     unsigned dummy; /* it's a parameter needed for dos_setdrive */
  739. #endif
  740.  
  741.     /* first deal with drive letter */
  742.  
  743.     if (isalpha(path[0]) && (path[1]==':')) {
  744.     int driveno=toupper(path[0])-'A'; /* 0=A, 1=B, ... */
  745. #if defined(ATARI)
  746.     (void)Dsetdrv(driveno);
  747. #endif
  748.  
  749. #if defined(__ZTC__)
  750.     (void)dos_setdrive(driveno + 1, &dummy);
  751. #endif
  752.  
  753. #if defined(MSDOS) && defined(__EMX__)
  754.     (void)_chdrive(driveno + 1);
  755. #endif
  756. #if defined(__MSC__)
  757.     (void)_chdrive(driveno+1);
  758. #endif
  759. #if (defined(MSDOS) || defined(_Windows)) && defined(__TURBOC__)
  760.     (void) setdisk(driveno);
  761. #endif
  762. #ifdef DJGPP
  763.     { union REGS r;
  764.         r.h.ah = 0x0e;
  765.         r.x.dx = driveno;
  766.         intdos(&r, &r);
  767.     }
  768. #endif
  769.     path += 2; /* move past drive letter */
  770.     }
  771.     /* then change to actual directory */
  772.     if (*path)
  773.     if (chdir(path))
  774.         return 1;
  775.  
  776.     return 0; /* should report error with setdrive also */
  777. #else /* MSDOS, ATARI etc. */
  778.     return chdir(path);
  779. #endif /* MSDOS, ATARI etc. */
  780. }
  781.  
  782. static void getpath(string)
  783. char *string;
  784. {
  785. #if 0 /* def DJGPP */
  786.     { union REGS r;
  787.         r.h.ah = 0x19;
  788.         intdos(&r, &r);
  789.         sprintf(string, "%c:", r.h.al + 'a');
  790.         string+=2;
  791.     }
  792. #endif
  793. #if (defined(unix) || defined(OSK))
  794. #ifdef GETCWD
  795.     (void) getcwd(string, MAX_LINE_LEN);    /* some Unix's use getcwd */
  796. #else
  797.     (void) getwd(string);    /* most Unix's use getwd */
  798. #endif
  799. #else /* unix */
  800. #ifdef __EMX__
  801.     (void) _getcwd2(string, MAX_ID_LEN);
  802. #else
  803.     /* Turbo C and VMS have getcwd() */
  804.     (void) getcwd(string, MAX_LINE_LEN);
  805. #endif
  806. #endif /* unix */
  807. }
  808.  
  809. static void replotrequest()
  810. {
  811.     int newlen;
  812.     int last_token;
  813.  
  814.     if (equals(c_token, "["))
  815.     int_error("cannot set range with replot", c_token);
  816.     if (!END_OF_COMMAND) {
  817.     last_token=num_tokens-1;
  818.     /* length = length of old part + length of new part + ',' + \0 */
  819.     newlen=strlen(replot_line)+token[last_token].start_index+token[last_token].length-token[c_token].start_index+2;
  820.     replot_line=ralloc(replot_line, (unsigned long)newlen, "extend replot line");
  821.     strcat(replot_line, ",");
  822.     capture(replot_line+strlen(replot_line), c_token, num_tokens - 1, newlen-strlen(replot_line));
  823.  
  824. #ifdef DEBUG_STR
  825.     fprintf(stderr, "new replot_line length %d\n", strlen(replot_line));
  826. #endif
  827.     }
  828.  
  829.     while(strlen(replot_line+1)>input_line_len)
  830.     extend_input_line();
  831.  
  832.     (void) strcpy(input_line, replot_line);
  833.     screen_ok = FALSE;
  834.     num_tokens = scanner(input_line);
  835.     c_token = 1;        /* skip the 'plot' part */
  836.     if(is_3d_plot)
  837.       plot3drequest();
  838.     else  plotrequest();
  839. }
  840.  
  841. #ifdef AMIGA_SC_6_1
  842. void 
  843. sleep(delay)
  844.     unsigned int    delay;
  845. {
  846.     Delay(50 * delay);
  847. }
  848. #endif
  849.  
  850. #ifdef AMIGA_AC_5
  851. void 
  852. sleep(delay)
  853.     unsigned int    delay;
  854. {
  855.     unsigned long   time_is_up;
  856.     time_is_up = time(NULL) + (unsigned long) delay;
  857.     while (time(NULL) < time_is_up)
  858.      /* wait */ ;
  859. }
  860. #endif
  861.  
  862. #if defined(MSDOS) || defined(_Windows) || defined(DOS386)
  863. #if (!defined(__TURBOC__) && !defined(__EMX__) && !defined(DJGPP)) || defined(_Windows) /* Turbo C already has sleep() */
  864. #ifndef __ZTC__            /* ZTC already has usleep() */
  865. /* kludge to provide sleep() for msc 5.1 */
  866. void 
  867. sleep(delay)
  868.     unsigned int    delay;
  869. {
  870.     unsigned long   time_is_up;
  871.     time_is_up = time(NULL) + (unsigned long) delay;
  872.     while (time(NULL) < time_is_up)
  873.      /* wait */ ;
  874. }
  875. #endif                /* not ZTC */
  876. #endif                /* (!TURBOC && !__EMX__ && !DJGPP) or _Windows */
  877. #endif                /* MSDOS || _Windows*/
  878.  
  879.  
  880. /* Support for input, shell, and help for various systems */
  881.  
  882. #ifdef vms
  883.  
  884. #include <descrip.h>
  885. #include <rmsdef.h>
  886. #include <smgdef.h>
  887. #include <smgmsg.h>
  888.  
  889. extern          lib$get_input(), lib$put_output();
  890. extern          smg$read_composed_line();
  891. extern        sys$putmsg();
  892. extern        lbr$output_help();
  893. extern        lib$spawn();
  894.  
  895. int             vms_len;
  896.  
  897. unsigned int    status[2] =
  898. {1, 0};
  899.  
  900. static char     Help[MAX_LINE_LEN + 1] = "gnuplot";
  901.  
  902. $DESCRIPTOR(prompt_desc, PROMPT);
  903. /* temporary fix until change to variable length */
  904. struct dsc$descriptor_s line_desc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
  905.  
  906. $DESCRIPTOR(help_desc, Help);
  907. $DESCRIPTOR(helpfile_desc, "GNUPLOT$HELP");
  908.  
  909. /* please note that the vms version of read_line doesn't support variable line
  910.    length (yet) */
  911.  
  912. static int read_line(prompt)
  913.     char           *prompt;
  914. {
  915.     int             more, start = 0;
  916.     char            expand_prompt[40];
  917.  
  918.     prompt_desc.dsc$w_length = strlen(prompt);
  919.     prompt_desc.dsc$a_pointer = prompt;
  920.     (void) strcpy(expand_prompt, "_");
  921.     (void) strncat(expand_prompt, prompt, 38);
  922.     do {
  923.     line_desc.dsc$w_length = MAX_LINE_LEN - start;
  924.     line_desc.dsc$a_pointer = &input_line[start];
  925.     switch (status[1] = smg$read_composed_line(&vms_vkid, 0, &line_desc, &prompt_desc, &vms_len)) {
  926.     case SMG$_EOF:
  927.         done(IO_SUCCESS);    /* ^Z isn't really an error */
  928.         break;
  929.     case RMS$_TNS:        /* didn't press return in time */
  930.         vms_len--;        /* skip the last character */
  931.         break;        /* and parse anyway */
  932.     case RMS$_BES:        /* Bad Escape Sequence */
  933.     case RMS$_PES:        /* Partial Escape Sequence */
  934.         sys$putmsg(status);
  935.         vms_len = 0;    /* ignore the line */
  936.         break;
  937.     case SS$_NORMAL:
  938.         break;        /* everything's fine */
  939.     default:
  940.         done(status[1]);    /* give the error message */
  941.     }
  942.     start += vms_len;
  943.     input_line[start] = '\0';
  944.     inline_num++;
  945.     if (input_line[start - 1] == '\\') {
  946.         /* Allow for a continuation line. */
  947.         prompt_desc.dsc$w_length = strlen(expand_prompt);
  948.         prompt_desc.dsc$a_pointer = expand_prompt;
  949.         more = 1;
  950.         --start;
  951.     } else {
  952.         line_desc.dsc$w_length = strlen(input_line);
  953.         line_desc.dsc$a_pointer = input_line;
  954.         more = 0;
  955.     }
  956.     } while (more);
  957.     return 0;
  958. }
  959.  
  960.  
  961. static void do_help()
  962. {
  963.     int first=c_token;
  964.     while (!END_OF_COMMAND)
  965.     ++c_token;
  966.  
  967.     strcpy(Help, "GNUPLOT ");
  968.     capture(Help+8, first, c_token-1, sizeof(Help)-9);
  969.     help_desc.dsc$w_length = strlen(Help);
  970.     if ((vaxc$errno = lbr$output_help(lib$put_output, 0, &help_desc,
  971.                &helpfile_desc, 0, lib$get_input)) != SS$_NORMAL)
  972.     os_error("can't open GNUPLOT$HELP", NO_CARET);
  973. }
  974.  
  975.  
  976. static void do_shell()
  977. {
  978.     if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
  979.     os_error("spawn error", NO_CARET);
  980.     }
  981. }
  982.  
  983.  
  984. static void do_system()
  985. {
  986.     input_line[0] = ' ';    /* an embarrassment, but... */
  987.  
  988.     if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
  989.     os_error("spawn error", NO_CARET);
  990.  
  991.     (void) putc('\n', stderr);
  992. }
  993.  
  994. #else                /* vms */
  995.  
  996. #ifdef _Windows
  997. static void do_help()
  998. {
  999.     if (END_OF_COMMAND)
  1000.         WinHelp(textwin.hWndParent,(LPSTR)winhelpname,HELP_INDEX,(DWORD)NULL);
  1001.     else {
  1002.         char buf[128];
  1003.         int start = c_token++;
  1004.         while (!(END_OF_COMMAND))
  1005.             c_token++;
  1006.         capture(buf, start, c_token-1, 128);
  1007.         WinHelp(textwin.hWndParent,(LPSTR)winhelpname,HELP_PARTIALKEY,(DWORD)buf);
  1008.     }
  1009. }
  1010. #else
  1011.  
  1012. /*
  1013.  * do_help: (not VMS, although it would work) Give help to the user. It
  1014.  * parses the command line into helpbuf and supplies help for that string.
  1015.  * Then, if there are subtopics available for that key, it prompts the user
  1016.  * with this string. If more input is given, do_help is called recursively,
  1017.  * with the argument the index of null character in the string. Thus a more
  1018.  * specific help can be supplied. This can be done repeatedly. If null input
  1019.  * is given, the function returns, effecting a backward climb up the tree.
  1020.  * David Kotz (David.Kotz@Dartmouth.edu) 10/89
  1021.  */
  1022.  
  1023. static void do_help()
  1024. {
  1025.     static char    *helpbuf = NULL;
  1026.     static char    *prompt = NULL;
  1027.     int             base;    /* index of first char AFTER help string */
  1028.     int             len;    /* length of current help string */
  1029.     TBOOLEAN         more_help;
  1030.     TBOOLEAN         only;    /* TRUE if only printing subtopics */
  1031.     int             subtopics;    /* 0 if no subtopics for this topic */
  1032.     int             start;    /* starting token of help string */
  1033.     char           *help_ptr;    /* name of help file */
  1034. #if defined(SHELFIND)
  1035.     static char    help_fname[256]=""; /* keep helpfilename across calls */
  1036. #endif
  1037. #if defined(MTOS) || defined(ATARI)
  1038.     char const *const ext[] = {NULL};
  1039. #endif
  1040.  
  1041.     if ((help_ptr = getenv("GNUHELP")) == (char *) NULL)
  1042. #ifndef SHELFIND
  1043.     /* if can't find environment variable then just use HELPFILE */
  1044.  
  1045. /* patch by David J. Liu for getting GNUHELP from home directory */
  1046. #if defined(__TURBOC__) && (defined(MSDOS) || defined(DOS386))
  1047.         help_ptr = HelpFile ;
  1048. #else
  1049. #if defined(MTOS) || defined(ATARI)
  1050.     {
  1051.     if ((help_ptr = findfile(HELPFILE,getenv("GNUPLOTPATH"),ext)) == NULL)
  1052.         help_ptr = findfile(HELPFILE,getenv("PATH"),ext);
  1053.     if (!help_ptr)    
  1054.         help_ptr = HELPFILE;
  1055.     }
  1056. #else
  1057.     help_ptr = HELPFILE;
  1058. #endif /* MTOS || ATARI */
  1059. #endif /* __TURBOC__ */
  1060. /* end of patch  - DJL */
  1061.  
  1062. #else
  1063.     /* try whether we can find the helpfile via shell_find. If not, just
  1064.        use the default. (tnx Andreas) */
  1065.  
  1066.     if( !strchr( HELPFILE, ':' ) && !strchr( HELPFILE, '/' ) &&
  1067.         !strchr( HELPFILE, '\\' ) ) {
  1068.         if( strlen(help_fname)==0 ) {
  1069.         strcpy( help_fname, HELPFILE );
  1070.         if( shel_find( help_fname )==0 ) {
  1071.             strcpy( help_fname, HELPFILE );
  1072.         }
  1073.         }
  1074.         help_ptr=help_fname;
  1075.     } else {
  1076.         help_ptr=HELPFILE;
  1077.     }
  1078. #endif /* SHELFIND */
  1079.  
  1080.     /* Since MSDOS DGROUP segment is being overflowed we can not allow such  */
  1081.     /* huge static variables (1k each). Instead we dynamically allocate them */
  1082.     /* on the first call to this function...                     */
  1083.     if (helpbuf == NULL) {
  1084.     helpbuf = alloc((unsigned long)MAX_LINE_LEN, "help buffer");
  1085.     prompt = alloc((unsigned long)MAX_LINE_LEN, "help prompt");
  1086.     helpbuf[0] = prompt[0] = 0;
  1087.     }
  1088.     len = base = strlen(helpbuf);
  1089.  
  1090.     /* find the end of the help command */
  1091.     for (start = c_token; !(END_OF_COMMAND); c_token++);
  1092.     /* copy new help input into helpbuf */
  1093.     if (len > 0)
  1094.     helpbuf[len++] = ' ';    /* add a space */
  1095.     capture(helpbuf + len, start, c_token - 1, MAX_LINE_LEN-len);
  1096.     squash_spaces(helpbuf + base);    /* only bother with new stuff */
  1097.     lower_case(helpbuf + base);    /* only bother with new stuff */
  1098.     len = strlen(helpbuf);
  1099.  
  1100.     /* now, a lone ? will print subtopics only */
  1101.     if (strcmp(helpbuf + (base ? base + 1 : 0), "?") == 0) {
  1102.     /* subtopics only */
  1103.     subtopics = 1;
  1104.     only = TRUE;
  1105.     helpbuf[base] = '\0';    /* cut off question mark */
  1106.     } else {
  1107.     /* normal help request */
  1108.     subtopics = 0;
  1109.     only = FALSE;
  1110.     }
  1111.  
  1112.     switch (help(helpbuf, help_ptr, &subtopics)) {
  1113.     case H_FOUND:{
  1114.         /* already printed the help info */
  1115.         /* subtopics now is true if there were any subtopics */
  1116.         screen_ok = FALSE;
  1117.  
  1118.         do {
  1119.         if (subtopics && !only) {
  1120.             /* prompt for subtopic with current help string */
  1121.             if (len > 0)
  1122.             (void) sprintf(prompt, "Subtopic of %s: ", helpbuf);
  1123.             else
  1124.             (void) strcpy(prompt, "Help topic: ");
  1125.             read_line(prompt);
  1126.             num_tokens = scanner(input_line);
  1127.             c_token = 0;
  1128.             more_help = !(END_OF_COMMAND);
  1129.             if (more_help)
  1130.             /* base for next level is all of current helpbuf */
  1131.             do_help();
  1132.         } else
  1133.             more_help = FALSE;
  1134.         } while (more_help);
  1135.  
  1136.         break;
  1137.     }
  1138.     case H_NOTFOUND:{
  1139.         printf("Sorry, no help for '%s'\n", helpbuf);
  1140.         break;
  1141.     }
  1142.     case H_ERROR:{
  1143.         perror(help_ptr);
  1144.         break;
  1145.     }
  1146.     default:{            /* defensive programming */
  1147.         int_error("Impossible case in switch", NO_CARET);
  1148.         /* NOTREACHED */
  1149.     }
  1150.     }
  1151.  
  1152.     helpbuf[base] = '\0';    /* cut it off where we started */
  1153. }
  1154. #endif  /* _Windows */
  1155.  
  1156. #ifdef AMIGA_AC_5
  1157. char            strg0[256];
  1158. #endif
  1159.  
  1160. static void do_system()
  1161. {
  1162. #ifdef AMIGA_AC_5
  1163.     char           *parms[80];
  1164.     void            getparms();
  1165.  
  1166.     getparms(input_line + 1, parms);
  1167.     if (fexecv(parms[0], parms) < 0)
  1168. #else
  1169. #if (defined(ATARI)&&defined(__GNUC__)) /* || (defined(MTOS)&&defined(__GNUC__)) */
  1170.     /* use preloaded shell, if available */
  1171.     short           (*shell_p) (char *command);
  1172.     void           *ssp;
  1173.  
  1174.     ssp = (void *) Super(NULL);
  1175.     shell_p = *(short (**) (char *)) 0x4f6;
  1176.     Super(ssp);
  1177.  
  1178.     /* this is a bit strange, but we have to have a single if */
  1179.     if ((shell_p ? (*shell_p) (input_line + 1) : system(input_line + 1)))
  1180. #else
  1181. #ifdef _Windows
  1182.     if (winsystem(input_line + 1))
  1183. #else
  1184.     if (system(input_line + 1))
  1185. #endif
  1186. #endif
  1187. #endif
  1188.     os_error("system() failed", NO_CARET);
  1189. }
  1190.  
  1191. #ifdef AMIGA_AC_5
  1192.  
  1193. /******************************************************************************/
  1194. /* */
  1195. /* Parses the command string (for fexecv use) and  converts the first token  */
  1196. /* to lower case                                                          */
  1197. /* */
  1198. /******************************************************************************/
  1199.  
  1200. void 
  1201. getparms(command, parms)
  1202.     char           *command;
  1203.     char          **parms;
  1204. {
  1205.     register int    i = 0;    /* A bunch of indices          */
  1206.     register int    j = 0;
  1207.     register int    k = 0;
  1208.  
  1209.     while (*(command + j) != '\0') {    /* Loop on string characters   */
  1210.     parms[k++] = strg0 + i;
  1211.     while (*(command + j) == ' ')
  1212.         ++j;
  1213.     while (*(command + j) != ' ' && *(command + j) != '\0') {
  1214.         if (*(command + j) == '"')    /* Get quoted string           */
  1215.         for (*(strg0 + (i++)) = *(command + (j++));
  1216.              *(command + j) != '"';
  1217.              *(strg0 + (i++)) = *(command + (j++)));
  1218.         *(strg0 + (i++)) = *(command + (j++));
  1219.     }
  1220.     *(strg0 + (i++)) = '\0';/* NUL terminate every token   */
  1221.     }
  1222.     parms[k] = '\0';
  1223.  
  1224.     for (k = strlen(strg0) - 1; k >= 0; --k)    /* Convert to lower case       */
  1225.     *(strg0 + k) >= 'A' && *(strg0 + k) <= 'Z' ? *(strg0 + k) |= 32 : *(strg0 + k);
  1226. }
  1227.  
  1228. #endif                /* AMIGA_AC_5 */
  1229.  
  1230. #ifdef READLINE
  1231. char           *
  1232. rlgets(s, n, prompt)
  1233.     char           *s;
  1234.     int             n;
  1235.     char           *prompt;
  1236. {
  1237.     static char    *line = (char *) NULL;
  1238.     static int     leftover = -1; /* index of 1st char leftover from last call */
  1239.  
  1240.     if(leftover== -1) {
  1241.     /* If we already have a line, first free it */
  1242.     if (line != (char *) NULL)
  1243.         free(line);
  1244.  
  1245.     line = readline((interactive) ? prompt : "");
  1246.     leftover=0;
  1247.     /* If it's not an EOF */
  1248.     if (line && *line) 
  1249.         add_history(line);
  1250.     }
  1251.     if(line) {
  1252.     strncpy(s, line+leftover, n);
  1253.     s[n-1]='\0';
  1254.     leftover+=strlen(s);
  1255.     if(line[leftover]=='\0')
  1256.         leftover = -1;
  1257.     return s;
  1258.     }
  1259.  
  1260.     return NULL;
  1261. }
  1262. #endif                /* READLINE */
  1263.  
  1264. #if defined(MSDOS) || defined(_Windows) || defined(DOS386)
  1265.  
  1266.  
  1267.  
  1268. static void do_shell()
  1269. {
  1270.     register char  *comspec;
  1271.     if ((comspec = getenv("COMSPEC")) == (char *) NULL)
  1272.     comspec = "\\command.com";
  1273. #ifdef _Windows
  1274.     if (WinExec(comspec, SW_SHOWNORMAL) <= 32)
  1275. #else
  1276. #ifdef DJGPP
  1277.     if (system(comspec) == -1)
  1278. #else
  1279.     if (spawnl(P_WAIT, comspec, NULL) == -1)
  1280. #endif
  1281. #endif
  1282.     os_error("unable to spawn shell", NO_CARET);
  1283. }
  1284.  
  1285. #else                /* MSDOS */
  1286. /* plain old Unix */
  1287.  
  1288. #ifdef AMIGA_SC_6_1
  1289. static void do_shell()
  1290. {
  1291.     register char  *shell;
  1292.     if (!(shell = getenv("SHELL")))
  1293.     shell = SHELL;
  1294.  
  1295.     if (system(shell))
  1296.     os_error("system() failed", NO_CARET);
  1297.  
  1298.     (void) putc('\n', stderr);
  1299. }
  1300. #else                /* AMIGA_SC_6_1 */
  1301. #ifdef OS2
  1302. static void do_shell()
  1303. {
  1304.     register char  *shell;
  1305.     if (!(shell = getenv("COMSPEC")))
  1306.     shell = SHELL;
  1307.  
  1308.     if (system(shell) == -1 )
  1309.     os_error("system() failed", NO_CARET);
  1310.  
  1311.     (void) putc('\n', stderr);
  1312. }
  1313. #else                           /* ! OS2 */
  1314. #define EXEC "exec "
  1315. static void do_shell()
  1316. {
  1317.     static char     exec[100] = EXEC;
  1318.     register char  *shell;
  1319.     if (!(shell = getenv("SHELL")))
  1320.     shell = SHELL;
  1321.  
  1322.     if (system(strncpy(&exec[sizeof(EXEC) - 1], shell,
  1323.                sizeof(exec) - sizeof(EXEC) - 1)))
  1324.     os_error("system() failed", NO_CARET);
  1325.  
  1326.     (void) putc('\n', stderr);
  1327. }
  1328. #endif                          /* OS2 */
  1329. #endif                /* AMIGA_SC_6_1 */
  1330. #endif                /* MSDOS */
  1331.  
  1332. /* read from stdin, everything except vms */
  1333.  
  1334. #ifndef READLINE
  1335. #if (defined(MSDOS) || defined(DOS386)) && !defined(_Windows) && !defined(__EMX__) && !defined(DJGPP)
  1336.  
  1337. /* if interactive use console IO so CED will work */
  1338.  
  1339. #define PUT_STRING(s) cputs(s)
  1340. #define GET_STRING(s,l) ((interactive) ? cgets_emu(s,l) : fgets(s,l,stdin))
  1341.  
  1342. #ifdef __TURBOC__ 
  1343. /* cgets implemented using dos functions */
  1344. /* Maurice Castro 22/5/91 */
  1345. char           *
  1346. doscgets(s)
  1347.     char           *s;
  1348. {
  1349.     long            datseg;
  1350.  
  1351.     /* protect and preserve segments - call dos to do the dirty work */
  1352.     datseg = _DS;
  1353.  
  1354.     _DX = FP_OFF(s);
  1355.     _DS = FP_SEG(s);
  1356.     _AH = 0x0A;
  1357.     geninterrupt(33);
  1358.     _DS = datseg;
  1359.  
  1360.     /* check for a carriage return and then clobber it with a null */
  1361.     if (s[s[1] + 2] == '\r')
  1362.     s[s[1] + 2] = 0;
  1363.  
  1364.     /* return the input string */
  1365.     return (&(s[2]));
  1366. }
  1367. #endif    /* __TURBOC__ */
  1368.  
  1369. #ifdef __ZTC__
  1370. void cputs(char *s)
  1371. {
  1372.    register int i = 0;
  1373.    while (s[i] != '\0')  bdos(0x02, s[i++], NULL);
  1374. }
  1375. char *cgets(char *s)
  1376. {
  1377.    bdosx(0x0A, s, NULL);
  1378.  
  1379.    if (s[s[1]+2] == '\r')
  1380.       s[s[1]+2] = 0;
  1381.  
  1382.    /* return the input string */
  1383.    return(&(s[2]));
  1384. }
  1385. #endif   /* __ZTC__ */
  1386.  
  1387. /* emulate a fgets like input function with DOS cgets */
  1388. char *cgets_emu(str, len)
  1389. char *str;
  1390. int len;
  1391. {
  1392.     static char buffer[128]="";
  1393.     static int leftover=0;
  1394.  
  1395.     if(buffer[leftover]=='\0') {
  1396.     buffer[0]=126;
  1397. #ifdef __TURBOC__
  1398.     doscgets(buffer);
  1399. #else
  1400.     cgets(buffer);
  1401. #endif
  1402.     fputc('\n', stderr);
  1403.     if(buffer[2]==26)
  1404.         return NULL;
  1405.     leftover=2;
  1406.     }
  1407.     strncpy(str, buffer+leftover, len);
  1408.     str[len-1]='\0';
  1409.     leftover+=strlen(str);
  1410.     return str;
  1411. }
  1412. #else /* !plain DOS */
  1413.  
  1414. #define PUT_STRING(s) fputs(s, stderr)
  1415. #define GET_STRING(s,l) fgets(s, l, stdin)
  1416.  
  1417. #endif
  1418. #endif /* READLINE */
  1419.  
  1420. static int read_line(prompt)
  1421.     char           *prompt;
  1422. {
  1423.     int             start = 0;
  1424.     TBOOLEAN        more = FALSE;
  1425.     int             last = 0;
  1426.  
  1427. #ifndef READLINE
  1428.     if (interactive)
  1429.     PUT_STRING(prompt);
  1430. #endif                /* READLINE */
  1431.     do {
  1432.     /* grab some input */
  1433. #ifdef READLINE
  1434.     if (((interactive)
  1435.          ? rlgets(&(input_line[start]), input_line_len - start,
  1436.               ((more) ? "> " : prompt))
  1437.          : fgets(&(input_line[start]), input_line_len - start, stdin))
  1438.         == (char *) NULL) {
  1439. #else
  1440.     if (GET_STRING(&(input_line[start]), input_line_len - start)
  1441.         == (char *) NULL) {
  1442. #endif                /* READLINE */
  1443.         /* end-of-file */
  1444.         if (interactive)
  1445.         (void) putc('\n', stderr);
  1446.         input_line[start] = '\0';
  1447.         inline_num++;
  1448.         if (start > 0)    /* don't quit yet - process what we have */
  1449.         more = FALSE;
  1450.         else
  1451.         return(1); /* exit gnuplot */
  1452.     } else {
  1453.         /* normal line input */
  1454.         last = strlen(input_line) - 1;
  1455.         if(last >= 0)
  1456.           {
  1457.         if (input_line[last] == '\n') {    /* remove any newline */
  1458.           input_line[last] = '\0';
  1459.           /* Watch out that we don't backup beyond 0 (1-1-1) */
  1460.           if (last > 0)
  1461.             --last;
  1462.         } else if (last + 2 >= input_line_len) {
  1463.           extend_input_line();
  1464.           start = last+1;
  1465.           more = TRUE;
  1466.           continue; /* read rest of line, don't print "> " */
  1467.         }
  1468.         
  1469.         if (input_line[last] == '\\') {    /* line continuation */
  1470.           start = last;
  1471.           more = TRUE;
  1472.         } else
  1473.           more = FALSE;
  1474.           }
  1475.         else
  1476.           more = FALSE;
  1477.     }
  1478. #ifndef READLINE
  1479.     if (more && interactive)
  1480.         PUT_STRING("> ");
  1481. #endif
  1482.     } while (more);
  1483.     return(0);
  1484. }
  1485. #endif                /* vms */
  1486.  
  1487. #ifdef _Windows
  1488. /* there is a system like call on MS Windows but it is a bit difficult to 
  1489.    use, so we will invoke the command interpreter and use it to execute the 
  1490.    commands */
  1491. int winsystem(s)
  1492. char *s;
  1493. {
  1494.     LPSTR comspec;
  1495.     LPSTR execstr;
  1496.     LPSTR p;
  1497.  
  1498.     /* get COMSPEC environment variable */
  1499. #ifdef WIN32
  1500.     char envbuf[81];
  1501.     GetEnvironmentVariable("COMSPEC", envbuf, 80);
  1502.     if (*envbuf == '\0')
  1503.         comspec = "\\command.com";
  1504.     else
  1505.         comspec = envbuf;
  1506. #else
  1507.     p = GetDOSEnvironment();
  1508.     comspec = "\\command.com";
  1509.     while (*p) {
  1510.         if (!strncmp(p,"COMSPEC=",8)) {
  1511.             comspec=p+8;
  1512.             break;
  1513.         }
  1514.         p+=strlen(p)+1;
  1515.     }
  1516. #endif
  1517.     /* if the command is blank we must use command.com */
  1518.     p = s;
  1519.     while ((*p == ' ') || (*p == '\n') || (*p == '\r'))
  1520.         p++;
  1521.     if (*p == '\0')
  1522.     {
  1523.         WinExec(comspec, SW_SHOWNORMAL);
  1524.         }
  1525.     else
  1526.     {
  1527.         /* attempt to run the windows/dos program via windows */
  1528.         if (WinExec(s, SW_SHOWNORMAL) <= 32)
  1529.         {
  1530.             /* attempt to run it as a dos program from command line */
  1531.             execstr = (char *) malloc(strlen(s) + strlen(comspec) + 6);
  1532.             strcpy(execstr, comspec);
  1533.             strcat(execstr, " /c ");
  1534.             strcat(execstr, s);
  1535.             WinExec(execstr, SW_SHOWNORMAL);
  1536.             free(execstr);
  1537.             }
  1538.         }
  1539.  
  1540.     /* regardless of the reality return OK - the consequences of */
  1541.     /* failure include shutting down Windows */
  1542.     return(0);        /* success */
  1543.     }
  1544. #endif
  1545.  
  1546. #if 0 /* not used */
  1547. static int 
  1548. get_time_data(line,maxcol,cols,types,x,y,z)
  1549. char *line;
  1550. int maxcol, *cols, *types;
  1551. double *x, *y, *z;
  1552. {
  1553.     register int m, n, linestat;
  1554.     double val[3];
  1555.     char *s;
  1556.     static struct tm tm;
  1557.  
  1558.     linestat = 1;
  1559.     m = n = 0;
  1560.     s = line;
  1561.     while ((linestat == 1) && (n<maxcol)) {
  1562.         while (isspace(*s)) s++;
  1563.         if (*s == '\0') {
  1564.             linestat = 0;
  1565.             break;
  1566.         }
  1567.         n++;
  1568.         if (n == cols[m]) {
  1569.             if ( types[m] == TIME ) {
  1570.                 if ((s = (char *) gstrptime(s,timefmt,&tm)) != NULL ) {
  1571.                     val[m] = (double) gtimegm(&tm);
  1572.                     m++;
  1573.                 } else
  1574.                     linestat = 2;
  1575.             } else if (isdigit(*s) || *s=='-' || *s=='+' || *s=='.') {
  1576.                 val[m] = atof(s);
  1577.                 m++;
  1578.             }
  1579.             else
  1580.                 linestat = 2;    /* abort the line non-digit in req loc */
  1581.         }
  1582.         while ((!isspace(*s)) && (*s != '\0')) s++;
  1583.     }
  1584.     if ( linestat == 2 )
  1585.         return(0);
  1586.     if ( m > 0 )
  1587.         *x = val[0];
  1588.     if ( m > 1 )
  1589.         *y = val[1];
  1590.     if ( m > 2 )
  1591.         *z = val[2];
  1592.     return(m);
  1593. }
  1594. #endif /* not used */
  1595.